﻿// WarframeAlert displays recent alerts from the WarframeAlerts Twitter feed.
// Copyright (C) 2013  Jeff Siebold aka NoonKnight
// Find updates of this program at <http://noonknight.com/WarframeAlert/>.
// Please send email to <noonknight@gmail.com> with WarframeAlert in the subject.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// The WindowPlacement class was taken from David Rickard's Tech Blog, "Thoughts
// on C#, WPF and programming in general":
// <http://blogs.msdn.com/b/davidrickard/archive/2010/03/09/saving-window-size-and-location-in-wpf-and-winforms.aspx>

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace WarframeAlert
{
	// RECT structure required by WINDOWPLACEMENT structure
	[Serializable()]
	[StructLayout(LayoutKind.Sequential)]
	public struct RECT
	{
		public int Left;
		public int Top;
		public int Right;
		public int Bottom;

		public RECT(int left, int top, int right, int bottom)
		{
			this.Left = left;
			this.Top = top;
			this.Right = right;
			this.Bottom = bottom;
		}
	}

	// POINT structure required by WINDOWPLACEMENT structure
	[Serializable()]
	[StructLayout(LayoutKind.Sequential)]
	public struct POINT
	{
		public int X;
		public int Y;

		public POINT(int x, int y)
		{
			this.X = x;
			this.Y = y;
		}
	}

	// WINDOWPLACEMENT stores the position, size, and state of a window
	[Serializable()]
	[StructLayout(LayoutKind.Sequential)]
	public struct WINDOWPLACEMENT
	{
		public int length;
		public int flags;
		public int showCmd;
		public POINT minPosition;
		public POINT maxPosition;
		public RECT normalPosition;
	}

	public static class WindowPlacement
	{
		private static Encoding encoding = new UTF8Encoding();
		private static XmlSerializer serializer = new XmlSerializer(typeof(WINDOWPLACEMENT));

		[DllImport("user32.dll")]
		private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

		[DllImport("user32.dll")]
		private static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);

		private const int SW_SHOWNORMAL = 1;
		private const int SW_SHOWMINIMIZED = 2;

		public static void SetPlacement(IntPtr windowHandle, String placementXml)
		{
			if (String.IsNullOrEmpty(placementXml))
			{
				return;
			}

			WINDOWPLACEMENT placement;
			byte[] xmlBytes = encoding.GetBytes(placementXml);

			try
			{
				using (MemoryStream memoryStream = new MemoryStream(xmlBytes))
				{
					placement = (WINDOWPLACEMENT)serializer.Deserialize(memoryStream);
				}

				placement.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
				placement.flags = 0;
				placement.showCmd = (placement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : placement.showCmd);
				SetWindowPlacement(windowHandle, ref placement);
			}
			catch (InvalidOperationException)
			{
				// Parsing placement XML failed. Fail silently.
			}
		}

		public static String GetPlacement(IntPtr windowHandle)
		{
			WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
			GetWindowPlacement(windowHandle, out placement);

			using (MemoryStream memoryStream = new MemoryStream())
			{
				using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8))
				{
					serializer.Serialize(xmlTextWriter, placement);
					byte[] xmlBytes = memoryStream.ToArray();
					return encoding.GetString(xmlBytes);
				}
			}
		}
	}
}
